/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package eu.games.esmi.ieat.indicatorvalues;

import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.PopupDateField;
import com.vaadin.ui.Tree;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window.Notification;
import eu.games.esmi.ieat.indicatorvalues.data.EMF;
import eu.games.esmi.ieat.indicatorvalues.data.GPIValues;
import eu.games.esmi.ieat.indicatorvalues.data.IndicatorSeries;
import it.polimi.games.epkb.controller.GpiKpiJpaController;
import it.polimi.games.epkb.controller.StoredValuesJpaController;
import it.polimi.games.epkb.entityClasses.GpiKpi;
import it.polimi.games.epkb.entityClasses.StoredValues;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;

/**
 *
 * @author user
 */
public class IndicatorAnalysisTab extends HorizontalLayout implements Tree.ValueChangeListener {

    IndicatorChart indicatorchart = new IndicatorChart("Indicator Analysis", null);
    PopupDateField startdate = new PopupDateField("From:");
    PopupDateField enddate = new PopupDateField("To:");
    Button btnReload = new Button("Reload");
    Set<String> selectedTreeItem = null;
    
    private final int querylimit = 10000;

    public IndicatorAnalysisTab() {
        super();
        init();

    }

    public void init() {

        this.setMargin(true);
        this.setSizeFull();

        Tree tree = new IndicatorTreeGenerator().createTree(IndicatorTreeGenerator.INDICATOR_TREE);
        tree.addListener(this);


        this.addComponent(tree);


        this.setComponentAlignment(tree, Alignment.TOP_LEFT);


        VerticalLayout vl = new VerticalLayout();

        startdate.setValue(new Date());
        startdate.setResolution(PopupDateField.RESOLUTION_DAY);
        startdate.setImmediate(true);


        enddate.setValue(new Date());
        enddate.setResolution(PopupDateField.RESOLUTION_DAY);
        enddate.setImmediate(true);

        btnReload.addListener(new Button.ClickListener() {

            public void buttonClick(ClickEvent event) {


                updateChart();

            }
        }); // react to clicks

        HorizontalLayout dates = new HorizontalLayout();

        dates.setSizeFull();
        dates.setMargin(true);
        dates.setSpacing(true);
        dates.addComponent(startdate);
        dates.setComponentAlignment(startdate, Alignment.BOTTOM_LEFT);
        dates.addComponent(enddate);
        dates.setComponentAlignment(enddate, Alignment.BOTTOM_LEFT);
        dates.addComponent(btnReload);
        dates.setComponentAlignment(btnReload, Alignment.BOTTOM_LEFT);
        dates.setExpandRatio(btnReload, 1.0f);


        vl.addComponent(dates);

        vl.addComponent(indicatorchart);
        vl.setComponentAlignment(indicatorchart, Alignment.TOP_LEFT);

        this.addComponent(vl);
        this.setExpandRatio(vl, 1.0f);


    }

    public void valueChange(ValueChangeEvent event) {

        Tree t = (Tree) event.getProperty();

        this.selectedTreeItem = (Set<String>) t.getValue();

        this.updateChart();

    }

    public void updateChart() {

        EntityManagerFactory emf = Persistence.createEntityManagerFactory(EMF.PU_NAME);

        GpiKpiJpaController indicatorsCtrl = new GpiKpiJpaController(emf);
        StoredValuesJpaController valuesCtrl = new StoredValuesJpaController(emf);

        LinkedList<IndicatorSeries> series = new LinkedList<IndicatorSeries>();



        for (String selectedItem : this.selectedTreeItem) {
            if (selectedItem.contains("-")) {
                String indicator = selectedItem.substring(0, selectedItem.indexOf("-"));

                String component = selectedItem.substring(selectedItem.indexOf("-") + 1);

                GpiKpi gpikpi = indicatorsCtrl.findGpiKpi(indicator);

                if (gpikpi != null) {
                    if ("avg".equalsIgnoreCase(component)) {

                        IndicatorSeries is = new IndicatorSeries(indicator + "(AVG)", null, "UM");

                        EntityManager em = emf.createEntityManager();


                        //Query q = em.createQuery("SELECT round(s.definitionTime/100)*100 as df, avg(s.computedValue) FROM StoredValues s WHERE s.idGPIKPI = :indicator GROUP BY df ORDER BY s.definitionTime DESC");
                        Query q = em.createNativeQuery("SELECT (UNIX_TIMESTAMP(round(definitiontime/100)*100)) as df, avg(computedvalue) FROM `epkb`.`stored_values` where id_gpi_kpi= ? and definitiontime >=? and definitiontime <=? group by df order by id desc");
                        q.setParameter(1, gpikpi.getId());
                        q.setParameter(2, this.startdate.getValue());
                        q.setParameter(3, this.enddate.getValue());
                        q.setMaxResults(querylimit);

                        List<Object[]> result = q.getResultList();

                        if (result.size() == querylimit) {

                            getWindow().showNotification("Warning",
                                    "With the selected dates more than " + this.querylimit + " items returned. Only the last " + this.querylimit + " are shown",
                                    Notification.TYPE_WARNING_MESSAGE);

                            Object[] first = result.get(0);
                            Date firstdate = new Date();
                            firstdate.setTime(((Long) first[0]).longValue() * 1000);

                            Object[] last = result.get(result.size() - 1);
                            Date lastdate = new Date();
                            lastdate.setTime(((Long) last[0]).longValue() * 1000);

                            this.startdate.setValue(firstdate);
                            this.enddate.setValue(lastdate);
                        }

                        //System.err.println("SELECT (UNIX_TIMESTAMP(round(definitiontime/100)*100)) as df, avg(computedvalue) FROM `epkb`.`stored_values` where id_gpi_kpi=" + gpikpi.getId() + " group by df order by id desc");
                        //System.out.println("elenco " + result.size());

                        is.setValues(GPIValues.getAvgValues(result, component, indicator));

                        is.setStatus(GPIValues.getAvgStatus(result, component, indicator));

                        is.setNrl(null);
                        is.setNrh(null);
                        is.setErl(null);
                        is.setErh(null);

                        series.add(is);


                    } else {


                        IndicatorSeries is = new IndicatorSeries(gpikpi.getName() + "(" + component + ")", null, "UM");

                        EntityManager em = emf.createEntityManager();


                        Query q = em.createQuery("SELECT s from StoredValues s WHERE s.idComponent.id = :idcomponent and s.idGPIKPI = :indicator AND s.definitionTime >= :start AND s.definitionTime <= :end ORDER BY s.definitionTime DESC");
                        q.setParameter("indicator", gpikpi);
                        q.setParameter("idcomponent", component);
                        q.setParameter("start", this.startdate.getValue());
                        q.setParameter("end", this.enddate.getValue());

                        q.setMaxResults(querylimit);

                        List<StoredValues> result = q.getResultList();

                        if (result.size() == querylimit) {

                            getWindow().showNotification("Warning",
                                    "With the selected dates more than " + this.querylimit + " items returned. Only the last " + this.querylimit + " are shown",
                                    Notification.TYPE_WARNING_MESSAGE);

                            StoredValues first = result.get(0);
                            StoredValues last = result.get(result.size() - 1);

                            this.startdate.setValue(first.getDefinitionTime());
                            this.startdate.setValue(last.getDefinitionTime());

                        }
                        is.setValues(GPIValues.getValues(result, component, indicator));

                        is.setStatus(GPIValues.getStatus(result, component, indicator));

                        is.setNrl(GPIValues.getNrl(component, indicator));
                        is.setNrh(GPIValues.getNrh(component, indicator));
                        is.setErl(GPIValues.getErl(component, indicator));
                        is.setErh(GPIValues.getErh(component, indicator));

                        series.add(is);

                    }
                }

                indicatorchart.setSeries(series);
            }
        }
        emf.close();

    }
}
